package adventure.placeable.trigger.results;

import adventure.Adventure;
import adventure.commands.skills.GenericSkill;
import adventure.commands.skills.Skill;
import adventure.placeable.Item;
import adventure.placeable.ItemImp;
import adventure.room.RoomManager;
import colour.ColourUtil;
import player.BookEntry;
import player.Player;
import player.PlayerEdit;
import server.util.Broadcaster;

/**
 *
 * @author Michael Hanns
 *
 */
public class ResultModifyPlayer extends TriggerResult implements Cloneable {

    private String modifyWhat;
    private String backupResultText;
    private boolean resultTextChanged;
    private Item item;
    private Skill skill;
    private BookEntry entry;
    private int intMod;
    private String strMod;

    public ResultModifyPlayer(String result, String modWhat, int uses,
            int intMod, String strMod, Item i, Skill s, BookEntry e) {
        super(result, uses);
        this.modifyWhat = modWhat;
        this.intMod = intMod;
        this.strMod = strMod;
        this.entry = e;
        this.backupResultText = result;
        this.resultTextChanged = false;
        this.item = i;
        this.skill = s;
    }

    public ResultModifyPlayer(String result, String modWhat, int intMod,
            String strMod, Item i, Skill s, BookEntry e) {
        super(result);
        this.modifyWhat = modWhat;
        this.intMod = intMod;
        this.strMod = strMod;
        this.entry = e;
        this.backupResultText = result;
        this.resultTextChanged = false;
        this.item = i;
        this.skill = s;
    }

    public ResultModifyPlayer(Adventure adv) {
        super();
        this.modifyWhat = "";
        this.intMod = 0;
        this.strMod = "";
        this.entry = null;
        this.backupResultText = super.getResultText();
        this.resultTextChanged = false;
        this.item = new ItemImp();
        this.skill = new GenericSkill(adv);
    }

    @Override
    public void setResultText(String result) {
        this.resultText = result;
        this.backupResultText = resultText;
    }

    public void setModifyWhat(String mod) {
        modifyWhat = mod;
    }

    public void setIntMod(int mod) {
        intMod = mod;
    }

    public void setStringMod(String mod) {
        strMod = mod;
    }
    
    public void setItem(Item i) {
        System.out.println("Setting item: " + i.getName());
        this.item = i;
    }
    
    public void setSkill(Skill s) {
        this.skill = s;
    }

    public void setEntry(BookEntry e) {
        entry = e;
    }

    public String getModifyWhat() {
        return modifyWhat;
    }

    public int getIntMod() {
        return intMod;
    }

    public String getStrMod() {
        return strMod;
    }
    
    public int getItemID() {
        return item.getID();
    }
    
    public int getSkillID() {
        return skill.getID();
    }

    public BookEntry getEntry() {
        return entry;
    }

    @Override
    public String getDescription() {
        if (super.limitedUses()) {
            String desc = super.resultText + ", uses: " + super.usesRemaining()
                    + " / MODPLAYER " + modifyWhat;
            return desc;
        } else {
            String desc = super.resultText + " / MODPLAYER " + modifyWhat;
            return desc;
        }
    }

    @Override
    public String resultImplementation(RoomManager r, Player p, String in, boolean previousFailed, Broadcaster out) {
        if (allConditionsMet(r, p, in, previousFailed)) {
            System.out.println("Deciding action..");
            boolean wasDead = p.isDead();
            decideAction(p);
            System.out.println("Using once..");
            useOnce();
            System.out.println("IntMod - " + intMod);

            String output = replaceCurrency(replaceKeywords(p), intMod);
            out.broadcastLocalToPlayer(p, replaceYou(output, p, true));

            // Add death notifications after replace keyboards!
            if ((wasDead != p.isDead()) && p.isDead()) {
                out.broadcastLocalToPlayer(p, ColourUtil.colourise(p.getAliveName(), ColourUtil.player) + " has been slain!");
                output += "\n" + "You been have slain!";
            } else if ((wasDead != p.isDead()) && !p.isDead()) {
                out.broadcastLocalToPlayer(p, ColourUtil.colourise(p.getAliveName(), ColourUtil.player) + " has been ressurected!");
                output += "\n" + "You been have ressurected!";
            }

            return replaceYou(output, p, false);
        } else {
            return "";
        }
    }

    @Override
    public String getType() {
        return "MODIFYPLAYER";
    }

    private void decideAction(Player p) {
        if (modifyWhat.equalsIgnoreCase("CURRENCY")) {
            p.giveCurrencyAmount(intMod);
        } else if (modifyWhat.equalsIgnoreCase("XP")) {
            super.resultText += "\n" + p.gainXP(intMod, false);
            resultTextChanged = true;
        } else if (modifyWhat.equalsIgnoreCase("HEALTH")) {
            ((PlayerEdit) p).setHealth(
                    Math.min(((PlayerEdit) p).getHealth() + intMod,
                    ((PlayerEdit) p).getMaxHealth()));
        } else if (modifyWhat.equalsIgnoreCase("SPECIAL")) {
            ((PlayerEdit) p).setSpecial(
                    Math.min(((PlayerEdit) p).getSpecial() + intMod,
                    ((PlayerEdit) p).getMaxSpecial()));
        } else if (modifyWhat.equalsIgnoreCase("MAXHEALTH")) {
            ((PlayerEdit) p).setMaxHealth(((PlayerEdit) p).getMaxHealth() + intMod);
        } else if (modifyWhat.equalsIgnoreCase("MAXSPECIAL")) {
            ((PlayerEdit) p).setMaxSpecial(((PlayerEdit) p).getMaxSpecial() + intMod);
        } else if (modifyWhat.equalsIgnoreCase("ATTACK")) {
            ((PlayerEdit) p).setAttack(p.getAttack() + intMod);
        } else if (modifyWhat.equalsIgnoreCase("DEFENCE")) {
            ((PlayerEdit) p).setDefence(p.getDefence() + intMod);
        } else if (modifyWhat.equalsIgnoreCase("INTELLIGENCE")) {
            ((PlayerEdit) p).setIntelligence(p.getIntelligence() + intMod);
        } else if (modifyWhat.equalsIgnoreCase("SPEED")) {
            ((PlayerEdit) p).setSpeed(p.getSpeed() + intMod);
        } else if (modifyWhat.equalsIgnoreCase("LUCK")) {
            ((PlayerEdit) p).setLuck(p.getLuck() + intMod);
        } else if (modifyWhat.equalsIgnoreCase("LEARNSKILL")) {
            if (skill != null) {
                p.learnSkill(skill);
            }
        } else if (modifyWhat.equalsIgnoreCase("FORGETSKILL")) {
            if (skill != null) {
                p.forgetSkill(skill);
            }
        } else if (modifyWhat.equalsIgnoreCase("GIVEITEM")) {
            p.giveItem(item);
        } else if (modifyWhat.equalsIgnoreCase("TAKEITEM")) {
            p.removeInventoryItem(item.getName());
        } else if (modifyWhat.equalsIgnoreCase("COMPLETELOG")) {
            p.completeLogEntry(intMod);
        } else if (modifyWhat.equalsIgnoreCase("ADDLOG")) {
            if (!p.hasLogEntry(intMod)) {
                System.out.println("Player doesn't have it, so giving..");
                p.newLogEntry(entry);
            }
            System.out.println(p.viewLogEntry(intMod));
        } else if (modifyWhat.equalsIgnoreCase("LEARNSKILL")) {
            if (!p.knowsSkill(intMod)) {
                p.newLogEntry(entry);
            }
            System.out.println(p.viewLogEntry(intMod));
        }
    }

    @Override
    public String replaceKeywords(Player p) {
        String finalText = resultText
                .replace("[PLAYER]", ColourUtil.colourise(p.getName(), ColourUtil.player))
                .replace("[ITEM]", ColourUtil.colourise(item.getName(), ColourUtil.item))
                .replace("[USES]", ColourUtil.colourise(super.usesRemaining() + "", ColourUtil.value))
                .replace("[INTMOD]", ColourUtil.colourise(intMod + "", ColourUtil.value))
                .replace("[STRMOD]", ColourUtil.colourise(strMod, ColourUtil.value))
                .replace("[SKILL]", ColourUtil.colourise(skill.getName() + "", skill.getTypeColour()));

        if (resultTextChanged) {
            resultText = backupResultText;
            resultTextChanged = false;
        }

        return finalText;
    }
}
